import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Queue;
import java.util.Set;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ConcurrentLinkedQueue;

/** This is a message reception and processing object for the
* Node class.
*/
public class NodeReceive implements Runnable
{
	/*
	LinkedBlockingQueue<String> commChannel;
	Map<Integer, LinkedBlockingQueue<String>> commChannels;
	Integer nodeId;
	boolean incomingMessage = false;
	Set<String> information;
	*/
	Node node;
    volatile Thread runFlag;
	
	public NodeReceive(Node node)
	{
		this.node = node;
        runFlag = null;
	}
	
	/*
	public NodeReceive(Integer nodeId)
	{
		this.nodeId = nodeId;
		commChannel = new LinkedBlockingQueue<String>();
		commChannels = new HashMap<Integer, LinkedBlockingQueue<String>>();
		information = new HashSet<String>();
	}
	
	public NodeReceive(Integer nodeId, NodeReceive node)
	{
		this.nodeId = nodeId;
		commChannel = new LinkedBlockingQueue<String>();
		commChannels = new HashMap<Integer, LinkedBlockingQueue<String>>();
		information = new HashSet<String>();
		commChannels.put(nodeId, node.commChannel);
	}
	*/
	
    // I think this belongs in Node itself, commenting out (JCW)
    /*
	public LinkedBlockingQueue<String> connect(Integer nodeId)
	{
		LinkedBlockingQueue<String> tmp = new LinkedBlockingQueue<String>();
		node.commChannels.put(nodeId, tmp);
		return tmp;
	}
	*/
    
    /** stop the listener from checking for incoming messages.
    * code modified from:
    * http://download.oracle.com/javase/1.4.2/docs/guide/misc/threadPrimitiveDeprecation.html
    */
    public void stopRunning()
    {
        // already stopped
        if(runFlag == null)
            return;
        
        // temporarily store the thread, negate flag and interrupt
        Thread t = runFlag;
        runFlag = null;
        t.interrupt();
    }
    
    
    /** Blocks for a message and processes it when available.
    */
	public void run()
	{
        runFlag = Thread.currentThread();
		while(runFlag != null)
		{
			try
			{
				String message = node.commChannel.take();
                /* moved to node.processMessage for inheritance aspect. (JCW)
                
				//System.out.println(message+","+node.nodeId);
				if(!node.information.contains(message))
				{
					//System.out.println("New Information");
					node.information.add(new String(message));
					for(LinkedBlockingQueue<String> q : node.commChannels.values())
					{
						//System.out.println("Adding Message");
						q.add(new String(message));
					}
				}else
                    node.copyCount++;
                */
                node.processMessage(message);
			}
			catch(InterruptedException e)
			{
                // only sent when thread is supposed to stop (no longer
                // listening) error handling not needed (JCW)
                /*
                // send to error, so it doesn't conflict with stdout
				e.printStackTrace(System.err);
                */
			}
		}
		
	}
}
